package com.virtualightning.mvvm.impl.proxy

import android.annotation.SuppressLint
import android.app.Activity
import android.content.pm.ActivityInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.res.AssetManager
import android.content.res.Resources
import android.text.TextUtils
import dalvik.system.DexClassLoader

/**
 *  Anchor : Create by CimZzz
 *  Time : 2021/1/27 16:16:22
 *  Project : zxs-new
 *  插件化管理器
 */
@Suppress("MemberVisibilityCanBePrivate", "unused", "DEPRECATION", "RemoveExplicitTypeArguments")
class HookManager private constructor(
    val apkPath: String,
    val dexOutDirPath: String,
    val assetManager: AssetManager,
    val resources: Resources,
    val classLoader: DexClassLoader,
    val packageInfo: PackageInfo
) {
    companion object {
        ///////////////////////////////////////////////////////////////////////////
        // Add by CimZzz on 2021/1/27 下午4:35
        // 缓存在内存中的 HookManager，避免每次调用都重新初始化一遍 HookManager
        ///////////////////////////////////////////////////////////////////////////
        private val hookManagerMap: HashMap<String, HookManager> by lazy { HashMap<String, HookManager>() }

        ///////////////////////////////////////////////////////////////////////////
        // Add by CimZzz on 2021/1/27 下午4:38
        // 清空指定的一个 HookManager
        ///////////////////////////////////////////////////////////////////////////
        fun removeHookManager(apkPath: String) {
            hookManagerMap.remove(apkPath)
        }

        ///////////////////////////////////////////////////////////////////////////
        // Add by CimZzz on 2021/1/27 下午4:37
        // 清空当前所有 HookManager
        ///////////////////////////////////////////////////////////////////////////
        fun clearHookManager() {
            hookManagerMap.clear()
        }

        ///////////////////////////////////////////////////////////////////////////
        // Add by CimZzz on 2021/1/27 下午4:37
        // 初始化 HookManager
        ///////////////////////////////////////////////////////////////////////////
        @SuppressLint("DiscouragedPrivateApi")
        fun initHookManager(activity: Activity, apkPath: String, dexOutDirPath: String): HookManager {
            val existHookManager = hookManagerMap[apkPath]
            if(existHookManager != null) {
                return existHookManager
            }
            val classLoader = DexClassLoader(apkPath, dexOutDirPath, null, activity.classLoader)
            val packageInfo = activity.packageManager.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES)!!
            val assetManager = AssetManager::class.java.newInstance()
            val addAssetPathMethod = AssetManager::class.java.getDeclaredMethod("addAssetPath", String::class.java)
            addAssetPathMethod.isAccessible = true
            addAssetPathMethod.invoke(assetManager, apkPath)
            val resources = Resources(assetManager, activity.resources.displayMetrics, activity.resources.configuration)
            val newHookManager = HookManager(apkPath, dexOutDirPath,
                assetManager, resources, classLoader, packageInfo)

            hookManagerMap[apkPath] = newHookManager
            return newHookManager
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/1/27 下午4:51
    // 根据 ActivityName 获取
    ///////////////////////////////////////////////////////////////////////////
    fun getActivityInfoByName(activityName: String) : ActivityInfo? {
        val activityInfoArray = packageInfo.activities ?: return null
        for(activityInfo in activityInfoArray) {
            if(TextUtils.equals(activityInfo.name, activityName)) {
                return activityInfo
            }
        }
        return null
    }
}